﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using Deployment.BuildManager.ExternalProcess.Common;

namespace Deployment.BuildManager.ExternalProcess.GetCompiledAssemblies
{
    public class BuildTask : IBuildTask
    {
        #region IBuildTask [ Members ]

        public SetupInfo Execute(SetupInfo info)
        {
            GetCompiledFilesFromFolder(info, info.CompiledPath); //Adiciona os arquivos na entidade.
            CopyCompiledAssemblies(info); //copia os compilados para pasta resource do projeto template.
            return info;
        }

        public void Cancel()
        {
            throw new NotImplementedException();
        }

        #endregion [ Members ]

        public void GetCompiledFilesFromFolder(SetupInfo info, string compiledPath)
        {
            if (Directory.Exists(compiledPath))
            {
                DirectoryInfo dir = new DirectoryInfo(compiledPath);

                List<string> files = (from d in dir.GetFiles("*.*", SearchOption.AllDirectories)
                                      select string.Concat(d.DirectoryName, Path.DirectorySeparatorChar, d.ToString())).ToList();

                foreach (string file in files)
                {
                    info.CompiledFiles.Add(
                        new ResourceItem
                        {
                            Name = this.GetAssemblyFileName(file),
                            CompiledFullPath = this.GetBuildFilePath(file),
                            ExtractionRelativePath = PSE.Deployment.Util.File.RemoveRootLevel(this.GetBuildFilePath(file))
                        });
                }
            }
        }

        private string GetAssemblyFileName(string resource)
        {
            string[] folders = resource.Split(Path.DirectorySeparatorChar);
            return folders.Last();
        }

        private void CopyCompiledAssemblies(SetupInfo info)
        {
            this.SendMessage("Copiando os Compilados Para a Pasta Resource do Projeto de Template...");
            foreach (ResourceItem item in info.CompiledFiles)
            {
                string buildPath = GetBuildFilePath(item.CompiledFullPath);
                string destinationDirectory = info.SetupTemplateProjectPath +
                                              Path.DirectorySeparatorChar +
                                              BuildConstants.ResourceFolder +
                                              Path.DirectorySeparatorChar + buildPath;

                if (!Directory.Exists(destinationDirectory))
                    Directory.CreateDirectory(destinationDirectory);

                string filePath = destinationDirectory + item.Name;

                if (File.Exists(filePath))
                    File.Delete(filePath);

                File.Copy(info.CompiledPath + Path.DirectorySeparatorChar + item.CompiledFullPath + item.Name, filePath);
            }
        }

        private string GetBuildFilePath(string assemblyFileName) // SetupInfo info)
        {
            string[] folders = assemblyFileName.Split(Path.DirectorySeparatorChar);

            List<string> foldersList = folders.ToList();
            int index = foldersList.FindIndex(
                delegate(string folderItem)
                {
                    return folderItem.Equals(BuildConstants.CompiledFolder);
                }
            );

            for (int i = index; i >= 0; i--)
                foldersList.RemoveAt(i);

            foldersList.RemoveAt(foldersList.Count - 1);
            folders = foldersList.ToArray();

            return String.Join(Path.DirectorySeparatorChar.ToString(), folders) + Path.DirectorySeparatorChar.ToString();
        }

        #region [ Events ]

        public event EventHandler<MessageEventArgs> MessageReceived;

        private void SendMessage(string message)
        {
            if (MessageReceived != null)
            {
                MessageEventArgs eventArgs = new MessageEventArgs(message);
                Logger.Log(message, Logger.EntryType.Information);
                MessageReceived(this, eventArgs);
            }
        }

        #endregion [ Events ]
    }
}
